#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <memory.h>
#include <malloc.h>
#include <errno.h>
#include <netinet/in.h>
#include "rfs-client.h"
int con_stblshd = 0;

int enviar(PACKAGE *package) {
    return write(package->from, package, sizeof (PACKAGE));
}

int recibir(PACKAGE *package) {
    // recibo el paquete
    int n = -1;
    n = read(package->from, package, sizeof (PACKAGE));
    return n;
}

void print_res(char * res) {
    printf("Resultado\n");
    printf("-----------------\n");
    printf("%s\n", res);
    printf("-----------------\n");
}

int
rls(PACKAGE *package) {
    // envío el comando
    package->op = RLS;
    enviar(package);
    // creo el puntero que va a contener el resultado final
    char output[MAX_STRING_SIZE];
    output[0] = '\0';

    do {
        // recibo el paquete
        if (recibir(package) < 0) {
            snprintf(output, MAX_STRING_SIZE, "Ocurrió un error recibiendo la respuesta.");
            continue;
        } else {
            // agrego la cadena que viene con el paquete
            strcat(output, package->data);
        }
    } while (package->offset == DATA_LENGTH);

    // imprimo resultado
    print_res(output);

    // retorno cantidad de paquetes leídos
    return package->block_count;
}

int
rcd(PACKAGE *package) {

    // envío el comando
    package->op = RCD;
    enviar(package);

    // creo el puntero que va a contener el resultado final
    char output[MAX_STRING_SIZE];
    output[0] = '\0';

    do {
        // recibo el paquete
        if (recibir(package) < 0) {
            snprintf(output, MAX_STRING_SIZE, "Ocurrió un error recibiendo la respuesta del puerto.");
            continue;
        } else {
            // agrego la cadena que viene con el paquete
            strcat(output, package->data);
        }
    } while (package->offset == DATA_LENGTH);

    // imprimo resultado
    print_res(output);

    // retorno cantidad de paquetes leídos
    return package->block_count;
}

int
get(PACKAGE * package) {
    char * file_name = (char *) malloc(DATA_LENGTH);
    strncpy(file_name, package->data, DATA_LENGTH);

    FILE * file = NULL;

    // creo el puntero que va a contener el resultado final
    char output[MAX_STRING_SIZE];
    output[0] = '\0';

    package->block_count = 0;
    int n, j;
    do {
        printf("===> %i\n", package->offset);
        package->op = GET;
        strncpy(package->data, file_name, DATA_LENGTH);
        enviar(package);
        if ((n = recibir(package)) < 0) {
            snprintf(output, MAX_STRING_SIZE, "Ocurrió un error al solicitar al servidor el archivo '%s'.\n"
                    "El servidor no respondió a la solicitud.", file_name);
            printf("0\n");
        } else
            if (package->op == OK) {
            if (file == NULL) {
                file = fopen(file_name, "w");
                printf("1\n");
            }
            // escribo el bloque del lado del cliente
            fwrite(package->data, sizeof (char), package->offset, file);
            printf("2\n");
            // preparo la llamada siguiente
            package->block_count++;
            // traigo el siguiente bloque
        } else {
            printf("3\n");
            snprintf(output, MAX_STRING_SIZE, "Ocurrió un error al intentar descargar el archivo.\n"
                    "El archivo '%s' no existe o el servidor no tiene permiso para leerlo.",
                    file_name);
            continue;
        }

    } while (package->offset == DATA_LENGTH);
    if (file != NULL)
        // cierro el archivo
        fclose(file);
    if (strlen(output) == 0) {
        int i = package->block_count;
        i--;
        i *= DATA_LENGTH;
        i += package->offset;
        snprintf(output, MAX_STRING_SIZE, "Se descargó correctamente el archivo '%s'.\n"
                "Se transmitieron %i bytes en total.",
                file_name, i);
    }
    print_res(output);

    free(file_name);
    return package->block_count;
}

int
put(PACKAGE * package) {
    char * file_name = (char *) malloc(DATA_LENGTH);
    strncpy(file_name, package->data, DATA_LENGTH);

    // creo el puntero que va a contener el resultado final
    char output[MAX_STRING_SIZE];
    output[0] = '\0';

    FILE * file = NULL;
    file = fopen(file_name, "r");

    int n, j, k, l;
    if (file != NULL) {
        package->block_count = 0;
        do {
            package->op = PUT;
            strncpy(package->data, file_name, DATA_LENGTH);
            //envío comando y nombre de archivo
            enviar(package);
            // recibo confirmación
            if ((n = recibir(package)) < 0) {
                snprintf(output, MAX_STRING_SIZE, "Ocurrió un error al solicitar al servidor subir el archivo %s.\n"
                        "No se ha recibido el OK del servidor.", file_name);
            } else
                // si no hubo error al crear el archivo en el servidor
                if (package->op == OK) {

                // leo el bloque
                package->offset = fread(package->data, sizeof (char), DATA_LENGTH, file);
                // envio el bloque
                enviar(package);
                // preparo la llamada siguiente
                package->block_count++;
            } else {
                printf("0\n");
                snprintf(output, MAX_STRING_SIZE, "Ocurrió un error al solicitar al servidor subir el archivo %s.\n"
                        "El servidor no pudo crear el archivo.", file_name);
                continue;
            }
            // hasta que haya leído y enviado una porción menor al tamaño máximo (señal del fin de archivo)
        } while (package->offset == DATA_LENGTH);
        if (file != NULL)
            // cierro el archivo
            fclose(file);
        if (strlen(output) == 0) {
            int i = package->block_count;
            i--;
            i *= DATA_LENGTH;
            i += package->offset;
            snprintf(output, MAX_STRING_SIZE, "Se subió correctamente el archivo '%s'.\n"
                    "Se transmitieron %i bytes en total.",
                    file_name, i);
        }
        free(file_name);
    } else {
        snprintf(output, MAX_STRING_SIZE, "El archivo %s no existe o no puede ser leído.", file_name);
    }
    print_res(output);
    return package->block_count;
}

int exit_client(PACKAGE * package) {
    int n = -1;
    // seteo fin de sesión
    package->op = QUIT;
    // envio el bloque
    enviar(package);
    if ((n = recibir(package)) < 0) {
        printf("Ocurrió un error recibiendo la respuesta del servidor al pedido de cierre de sesión.\n");
    }

    if (n >= 0 && package->op == OK)
        return OK;

    return ERROR;
}
